package xing.service.controller;

import com.alibaba.fastjson.JSONObject;
import com.dingtalk.oapi.lib.aes.DingTalkEncryptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import xing.application.api.Env;
import xing.application.service.isv.suite.DingConfigService;
import xing.application.service.isv.suite.SuiteAuthService;
import xing.application.service.isv.suite.SuiteTicketService;
import xing.domain.isv.suite.Suite;
import xing.infrastructure.data.CallResult;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

@RestController
@RequestMapping("/suite")
public class SuiteCallBackControllerTest {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private SuiteTicketService suiteTicketService;
    @Autowired
    private SuiteAuthService suiteService;
    @Autowired
    private DingConfigService dingConfigService;
    @Autowired
    private SuiteAuthService suiteAuthService;

    @PostMapping(value = "/test/create")
    public Map<String, String> suiteCreate(@RequestParam(value = "signature", required = false) String signature,
                                           @RequestParam(value = "timestamp", required = false) String timestamp,
                                           @RequestParam(value = "nonce", required = false) String nonce,
                                           @RequestBody(required = false) JSONObject json){
        try{
            /**
             * token,aseKey这两个参数在注册套件的时候,填写的。如果不想改代码,那么注册套件的时候也可以填写下面的两个数值
             * 要注意信息安全哦.
             */
            DingTalkEncryptor dingTalkEncryptor = new DingTalkEncryptor(Env.TOKEN, Env.ENCODING_AES_KEY, Env.CREATE_SUITE_KEY);
            String encryptMsg = json.getString("encrypt");
            String plainText = dingTalkEncryptor.getDecryptMsg(signature, timestamp, nonce, encryptMsg);
            JSONObject callbackMsgJson = JSONObject.parseObject(plainText);
            String random = callbackMsgJson.getString("Random");
            String responseEncryMsg = random;
            Map<String, String> encryptedMap = dingTalkEncryptor.getEncryptedMap(responseEncryMsg, System.currentTimeMillis(), com.dingtalk.oapi.lib.aes.Utils.getRandomStr(8));
            return encryptedMap;
        }catch (Exception e){
            logger.error("创建套件错误",e);
            return null;
        }
    }

    @PostMapping(value = "/test/callback/{suiteKey}")
    public Map<String, String> receiveCallBack(@PathVariable(value="suiteKey", required = false) String suiteKey,
                                    @RequestParam(value = "signature", required = false) String signature,
                                    @RequestParam(value = "timestamp", required = false) String timestamp,
                                    @RequestParam(value = "nonce", required = false) String nonce,
                                    @RequestBody(required = false) JSONObject json){
        logger.info("获取的参数按顺序为"+signature+","+timestamp+","+nonce);

        try {
            /**
             * token,aseKey这两个参数在注册套件的时候,填写的。如果不想改代码,那么注册套件的时候也可以填写下面的两个数值
             * 要注意信息安全哦.
             */
            Suite suite=suiteService.getSuiteByKey(suiteKey);
            DingTalkEncryptor dingTalkEncryptor = new DingTalkEncryptor(suite.getToken(), suite.getEncodingAesKey(), suite.getSuiteKey());
            String encryptMsg = json.getString("encrypt");
            String plainText = dingTalkEncryptor.getDecryptMsg(signature, timestamp, nonce, encryptMsg);
            /*
			 *  对从encrypt解密出来的明文进行处理
			 *  不同的eventType的明文数据格式不同
			 */
            JSONObject callbackMsgJson = JSONObject.parseObject(plainText);
            String eventType = callbackMsgJson.getString("EventType");
			/* res是需要返回给钉钉服务器的字符串，一般为success
			 * "check_create_suite_url"和"check_update_suite_url"事件为random字段
			 * 具体请查看文档或者对应eventType的处理步骤
			 */
            String res = "success";
            switch (eventType) {
                case "suite_ticket":
                    /*"suite_ticket"事件每二十分钟推送一次,数据格式如下
				    {
					  "SuiteKey": "suitexxxxxx",
					  "EventType": "suite_ticket ",
					  "TimeStamp": 1234456,
					  "SuiteTicket": "adsadsad"
					}
				    */
                    logger.info("进入suite_ticket事件");
                    String suiteTicket = callbackMsgJson.getString("SuiteTicket");
                    logger.info("获取的suite_ticket为"+suiteTicket);
                    /*
                     * ISV应当把最新推送的suiteTicket做持久化存储，
                     * 以防重启服务器之后丢失了当前的suiteTicket
                     *
                     */
                    try {
                        suiteTicketService.saveOrUpdateSuiteTicket(suiteKey,suiteTicket);
                    } catch (Exception e) {
                        logger.error("保存suite_ticket失败",e);
                        res = "faile";
                    }
                    break;
                case "tmp_auth_code":
                    logger.info("进入tmp_auth_code事件");
                    /*"tmp_auth_code"事件将企业对套件发起授权的时候推送
                          数据格式如下
                        {
                          "SuiteKey": "suitexxxxxx",
                          "EventType": " tmp_auth_code",
                          "TimeStamp": 1234456,
                          "AuthCode": "adads"
                        }
                    */
                    String tmpAuthCode = callbackMsgJson.getString("AuthCode");

                    CallResult r= suiteAuthService.saveOrUpdateSuiteAuth(suiteKey,tmpAuthCode);
                    if(!r.isSuccess()){
                        res = "faile";
                    }
                    break;
                case "change_auth":
                    logger.info("进入change_auth事件");
                    /*"change_auth"事件将在企业授权变更消息发生时推送
                         * 数据格式如下
                        {
                          "SuiteKey": "suitexxxxxx",
                          "EventType": " change_auth",
                          "TimeStamp": 1234456,
                          "AuthCorpId": "xxxxx"
                        }
                    */

                    String corpid = callbackMsgJson.getString("AuthCorpID");
                    // 由于以下操作需要从持久化存储中获得数据，而本demo并没有做持久化存储（因为部署环境千差万别），所以没有具体代码，只有操作指导。
                    // 1.根据corpid查询对应的permanent_code(永久授权码)
                    // 2.调用『企业授权的授权数据』接口（ServiceHelper.getAuthInfo方法），此接口返回数据具体详情请查看文档。
                    // 3.遍历从『企业授权的授权数据』接口中获取所有的微应用信息
                    // 4.对每一个微应用都调用『获取企业的应用信息接口』（ServiceHelper.getAgent方法）
                    /*
                     * 5.获取『获取企业的应用信息接口』接口返回值其中的"close"参数，才能得知微应用在企业用户做了授权变更之后的状态，有三种状态码
                     * 	分别为0，1，2.含义如下：
                     *  0:禁用（例如企业用户在OA后台禁用了微应用）
                     *  1:正常 (例如企业用户在禁用之后又启用了微应用)
                     *  2:待激活 (企业已经进行了授权，但是ISV还未为企业激活应用)
                     *  再根据具体状态做具体操作。
                     */
                    break;
                case "check_create_suite_url":
                    logger.info("进入check_create_suite_url事件");
                    /*"check_create_suite_url"事件将在创建套件的时候推送
                     * {
                          "EventType":"check_create_suite_url",
                          "Random":"brdkKLMW",
                          "TestSuiteKey":"suite4xxxxxxxxxxxxxxx"
                        }
                     */
                    //此事件需要返回的"Random"字段，
                    res = callbackMsgJson.getString("Random");
//                    String testSuiteKey = callbackMsgJson.getString("TestSuiteKey");
                    break;
                case "check_update_suite_url":
                    logger.info("进入check_update_suite_url事件");
                    /* "check_update_suite_url"事件将在更新套件的时候推送
                     * {
                          "EventType":"check_update_suite_url",
                          "Random":"Aedr5LMW",
                          "TestSuiteKey":"suited6db0pze8yao1b1y"

                        }
                     */
                    res = callbackMsgJson.getString("Random");
                    break;
            }
                Map<String, String> encryptedMap = dingTalkEncryptor.getEncryptedMap(res, Long.parseLong(timestamp), nonce);
            return encryptedMap;
        } catch (Exception e) {
            logger.error("回调出错",e);
        }
        return null;
    }

    /**
     * 描    述：获取config
     * 创 建 人：陈天龙
     * 日    期：2017/8/28
     * @param corpId
     * @param appId
     * @return CallResult
     */
    @GetMapping(value = "test/{corpId}/{appId}/config")
    public CallResult getConfig(@PathVariable("appId") Long appId, @PathVariable("corpId") String corpId
            , HttpServletRequest request){
        CallResult callResult = null;
        try {
            String url = request.getHeader("referer");
            logger.info("获取的url为"+url);
            callResult = dingConfigService.getConfig(corpId,appId,url);
        } catch (Exception e) {
            callResult = CallResult.error("获取config失败");
            logger.error("获取config失败",e);
        }
        return callResult;
    }
}

